;; 在framebuffer中绘制希尔伯特曲线
;; 希尔伯特曲线是一种空间填充曲线，通过递归算法实现

;; 主程序入口
main:
    ;; 清空画布 - 用循环清空整个屏幕
    PUSH 0           ; 初始y=0
    clear_y_loop:
    PUSH 0           ; 初始x=0
    clear_x_loop:
    
    ;; 设置当前坐标的字符为空格(32) - 参数顺序: x, y, char
    DUP              ; 复制x
    SWAP             ; 交换x和y，现在栈顶是y
    OVER             ; 复制x，现在栈顶是x
    PUSH 32          ; 空格字符
    SETU             ; 设置字符
    
    ;; x加1
    PUSH 1
    ADD
    
    ;; 检查x是否小于64
    DUP
    PUSH 64
    LT
    JUMPIF clear_x_loop  ; 如果x<64，继续内层循环
    
    ;; x循环结束，y加1
    POP              ; 弹出x
    SWAP             ; 交换，让y在栈顶
    PUSH 1
    ADD
    DUP              ; 复制y
    PUSH 64
    LT
    JUMPIF clear_y_loop  ; 如果y<64，继续外层循环
    
    POP              ; 弹出y
    
    ;; 绘制希尔伯特曲线
    ;; 参数: x, y, size, orientation, level
    PUSH 2           ; 起始x坐标
    PUSH 2           ; 起始y坐标
    PUSH 60          ; 曲线大小
    PUSH 0           ; 初始方向 (0=右, 1=下, 2=左, 3=上)
    PUSH 4           ; 递归深度
    CALL hilbert_curve
    
    HALT

;; 希尔伯特曲线递归函数
;; 参数: x, y, size, orientation, level
hilbert_curve:
    ;; 保存返回地址
    SWAP
    DUP
    SWAP
    
    ;; 检查递归深度
    DUP              ; 复制level
    PUSH 0
    EQ
    JUMPIF hilbert_base_case
    
    ;; 递归调用 - 减小深度
    SWAP
    PUSH 1
    SUB
    SWAP
    
    ;; 根据方向绘制四个子曲线
    DUP              ; 复制orientation
    PUSH 0
    EQ
    JUMPIF hilbert_orientation_0
    
    DUP
    PUSH 1
    EQ
    JUMPIF hilbert_orientation_1
    
    DUP
    PUSH 2
    EQ
    JUMPIF hilbert_orientation_2
    
    ;; 方向3 (上)
    JUMP hilbert_orientation_3

hilbert_base_case:
    ;; 基础情况 - 绘制单个点
    POP              ; 弹出level
    POP              ; 弹出orientation
    POP              ; 弹出size
    SWAP             ; 交换x和y
    PUSH #x2588      ; 实心方块字符
    SETU             ; 设置字符
    RET

hilbert_orientation_0:
    ;; 方向0 (右)
    POP              ; 弹出orientation
    
    ;; 第一个子曲线 (左下)
    DUP              ; 复制size
    PUSH 2
    DIV
    SWAP             ; 保存一半大小
    
    PUSH 3           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y
    OVER             ; 复制x
    CALL hilbert_curve
    
    ;; 向下连接线
    OVER             ; 复制y
    PUSH 1
    ADD
    SWAP             ; 交换x和y
    PUSH #x2502      ; 垂直线字符
    SETU
    
    ;; 第二个子曲线 (右下)
    PUSH 0           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y+1
    OVER             ; 复制x
    PUSH 1
    ADD
    CALL hilbert_curve
    
    ;; 向右连接线
    OVER             ; 复制x+1
    PUSH 1
    ADD
    SWAP             ; 交换x和y
    PUSH #x2500      ; 水平线字符
    SETU
    
    ;; 第三个子曲线 (右上)
    PUSH 0           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y+1
    OVER             ; 复制x+2
    CALL hilbert_curve
    
    ;; 向上连接线
    OVER             ; 复制y+1
    PUSH 1
    SUB
    SWAP             ; 交换x和y
    PUSH #x2502      ; 垂直线字符
    SETU
    
    ;; 第四个子曲线 (左上)
    PUSH 1           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y
    OVER             ; 复制x+2
    CALL hilbert_curve
    
    RET

hilbert_orientation_1:
    ;; 方向1 (下)
    POP              ; 弹出orientation
    
    ;; 第一个子曲线 (右上)
    DUP              ; 复制size
    PUSH 2
    DIV
    SWAP             ; 保存一半大小
    
    PUSH 0           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y
    OVER             ; 复制x
    CALL hilbert_curve
    
    ;; 向右连接线
    OVER             ; 复制x
    PUSH 1
    ADD
    SWAP             ; 交换x和y
    PUSH #x2500      ; 水平线字符
    SETU
    
    ;; 第二个子曲线 (右下)
    PUSH 1           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y
    OVER             ; 复制x+1
    CALL hilbert_curve
    
    ;; 向下连接线
    OVER             ; 复制y
    PUSH 1
    ADD
    SWAP             ; 交换x和y
    PUSH #x2502      ; 垂直线字符
    SETU
    
    ;; 第三个子曲线 (左下)
    PUSH 1           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y+1
    OVER             ; 复制x+1
    CALL hilbert_curve
    
    ;; 向左连接线
    OVER             ; 复制x+1
    PUSH 1
    SUB
    SWAP             ; 交换x和y
    PUSH #x2500      ; 水平线字符
    SETU
    
    ;; 第四个子曲线 (左上)
    PUSH 2           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y+1
    OVER             ; 复制x
    CALL hilbert_curve
    
    RET

hilbert_orientation_2:
    ;; 方向2 (左)
    POP              ; 弹出orientation
    
    ;; 第一个子曲线 (右上)
    DUP              ; 复制size
    PUSH 2
    DIV
    SWAP             ; 保存一半大小
    
    PUSH 1           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y
    OVER             ; 复制x
    CALL hilbert_curve
    
    ;; 向上连接线
    OVER             ; 复制y
    PUSH 1
    SUB
    SWAP             ; 交换x和y
    PUSH #x2502      ; 垂直线字符
    SETU
    
    ;; 第二个子曲线 (左上)
    PUSH 2           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y-1
    OVER             ; 复制x
    CALL hilbert_curve
    
    ;; 向左连接线
    OVER             ; 复制x
    PUSH 1
    SUB
    SWAP             ; 交换x和y
    PUSH #x2500      ; 水平线字符
    SETU
    
    ;; 第三个子曲线 (左下)
    PUSH 2           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y-1
    OVER             ; 复制x-1
    CALL hilbert_curve
    
    ;; 向下连接线
    OVER             ; 复制y-1
    PUSH 1
    ADD
    SWAP             ; 交换x和y
    PUSH #x2502      ; 垂直线字符
    SETU
    
    ;; 第四个子曲线 (右下)
    PUSH 3           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y
    OVER             ; 复制x-1
    CALL hilbert_curve
    
    RET

hilbert_orientation_3:
    ;; 方向3 (上)
    POP              ; 弹出orientation
    
    ;; 第一个子曲线 (左下)
    DUP              ; 复制size
    PUSH 2
    DIV
    SWAP             ; 保存一半大小
    
    PUSH 2           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y
    OVER             ; 复制x
    CALL hilbert_curve
    
    ;; 向左连接线
    OVER             ; 复制x
    PUSH 1
    SUB
    SWAP             ; 交换x和y
    PUSH #x2500      ; 水平线字符
    SETU
    
    ;; 第二个子曲线 (左上)
    PUSH 3           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y
    OVER             ; 复制x-1
    CALL hilbert_curve
    
    ;; 向上连接线
    OVER             ; 复制y
    PUSH 1
    SUB
    SWAP             ; 交换x和y
    PUSH #x2502      ; 垂直线字符
    SETU
    
    ;; 第三个子曲线 (右上)
    PUSH 3           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y-1
    OVER             ; 复制x-1
    CALL hilbert_curve
    
    ;; 向右连接线
    OVER             ; 复制x-1
    PUSH 1
    ADD
    SWAP             ; 交换x和y
    PUSH #x2500      ; 水平线字符
    SETU
    
    ;; 第四个子曲线 (右下)
    PUSH 0           ; 新方向
    OVER             ; 复制一半大小
    OVER             ; 复制y-1
    OVER             ; 复制x
    CALL hilbert_curve
    
    RET

;; 工具函数：绘制连接线
;; 参数: x, y, char
draw_line:
    DUP              ; 复制char
    SWAP             ; 交换char和y
    OVER             ; 复制x
    SETU             ; 设置字符
    RET